library(proto)

#' Simulation module object. 
#' 
#' A simulation module is really the core of a simulation. It contains the code and output for a distinct set 
#' of results generated, eg: health outcomes for years 1 - 10. 
#'  
#' It contains the following key elements:
#' 
#' outcomes - a list of all outcome matrices for the Simmodule.
#' 
#' each Simmodule has a \code{simulateRun} method which transforms the simframe. Typically, transformations will 
#' move variables for micro-units in the simframe through multiple iterations (or time steps).  
#' At the end of each iteration, for outcome variables (as defined in the simframe), the current values 
#' for all micro-units are stored in an outcome matrix.
#' An outcome matrix contains the set of values for each micro-unit during each iteration.
#' 
#' At the end of each run a set of run stats is calculated for outcomes. A run stat is essentially a function that takes
#' an outcome matrix and produces an aggregate value for each iteration. 
#' This aggregate value may be a single value (eg: mean), a vector (eg: frequencies, quantiles, summary), 
#' or a matrix (eg: 2 way table). 
#' 
#' Run stats are averaged across multiple runs by collateRunStats to get a final simulation result.
#'
#' @export 
Simmodule <- proto(
expr = {
			
	#' Creates a new object. 
	#' 
	#' @param .
	#'  Simmodule receiving object.
	#' @param name
	#'  name of this object
	#' 
	#' @return 
	#'  a new simmodule object
	#' 
	#' @export 
	#' @examples 
	#' .super$new(., name="Demo")
	new <- function(., name) {
		# return new object
		proto(.,
				name=name,
				outcomes=list(),
				run_results=list(),
				run_results_collated=list()
		)
	}

	
	#' Simulate outomes and store them in the outcomes list.
	#' 
	#' Sub-classes should extend this function.
	#' 
	#' @param .
	#'  Simmodule receiving object
	#' @param simenv
	#'  simulation environment object
	#' 
	#' @return 
	#' any object. Stored in the outcomes list. 
	#' 
	#' @export 
	#' @example 
	#' 
	#' NB: simenv$simframe will be re-used in subsequent runs so should NOT be modified
	simulateRun <- function (., simenv) {
		
	}

	
	#' Map outcomes to run results for a single run. Run results are typically 
	#' descriptive statistics (eg: freqs, means, etc) generated for variables 
	#' in outcomes. 
	#' 
	#' @param .
	#'  receiving object. 
	#' 
	#' @param simframe
	#'  the simulation environment's simframe. Useful for accessing adjusted variables.
	#' 
	#' @param outcomes
	#'  the list of outcome matrices generated by simulateRun()
	#' 
	#' @return 
	#'  any object. Stored in the run_results list by run. 
	#' 
	#' @examples
	#'  . <- env.base$modules$demo
	#'  outcomes <- .$outcomes
	map_outcomes_to_run_results <- function(., simframe, outcomes) {
		
	}
	
	
	#' Collates (ie: reduces) all run results to averaged values and labels collated results.
	#'
	#' @param .
	#'  receiving object. 
	#' 
	#' @param all_run_results
	#'  the list of all run results generated by map_outcomes_to_run_results() 
	#' 
	#' @return
	#'  any object. Stored in the run_results_collated list.
	#' 
	#' @examples 
	#' . <- env.base$modules$demo
	#' all_run_results <- .$run_results
	collate_all_run_results <- function(., all_run_results) {
		
	}
	
	
	
	
	clone <- function(.) as.proto(.$as.list(all.names=TRUE))
	
	

	class <- function(.) "Simmodule"
})
